/*
 * Created by Jaren at 2023/9/4 14:40
 */
import 'dart:typed_data';

import 'package:inmotion_protocol/common/mode.dart';
import 'package:inmotion_protocol/common/vehicle_info.dart';
import 'package:inmotion_protocol/ezcan/bean/real_time_info.dart';
import 'package:inmotion_protocol/util/byte_util.dart';

class R1RealTimeInfo extends AbsRealTimeInfo {
  R1RealTimeInfo(super.property);

  R1RealTimeInfo.fromFastMsgRsp(ProductProperty property, Uint8ClampedList bytes) : super.fromBytes(property, bytes) {
    speed = ByteUtil.toInt16(ByteUtil.bytes2IntLe(bytes, 12, 4) ~/ 38.12);
    totalMileage = ByteUtil.toUint32(ByteUtil.bytes2Uint64Le(bytes, 44) ~/ 571101.6379455429);
    batteryLevel = ByteUtil.toUint16(calBatteryLevel(voltage.value) * 100);
  }

  @override
  String toString() {
    return 'R1RealTimeInfo{${super.toString()}';
  }

  int calBatteryLevel(int voltage) {
    if (voltage > 8200) {
      return 100;
    } else if (voltage > 7780) {
      return ((((voltage - 7780) / (8200 - 7780)) * 0.2 + 0.8) * 100).toInt();
    } else if (voltage > 7480) {
      return ((((voltage - 7480) / (7780 - 7480)) * 0.2 + 0.6) * 100).toInt();
    } else if (voltage > 7180) {
      return ((((voltage - 7180) / (7480 - 7180)) * 0.2 + 0.4) * 100).toInt();
    } else if (voltage > 7030) {
      return ((((voltage - 7030) / (7180 - 7030)) * 0.2 + 0.2) * 100).toInt();
    } else if (voltage > 6800) {
      return ((((voltage - 6800) / (7030 - 6800)) * 0.2) * 100).toInt();
    } else {
      return 0;
    }
  }
}

class R1RealTimeState extends AbsRealTimeState {
  R1RealTimeState.fromFastMsgRsp(Uint8ClampedList bytes, [int offset = 0]) : super.fromBytes(bytes, offset) {
    int mode = ByteUtil.bytes2Uint32Le(bytes, 60).value;
    pcModeValue = ByteUtil.toUint32(mode & 0x0F);
    switch (pcModeValue.value) {
      case 0x0:
        pcMode = Mode.idle;
        break;
      case 0x01:
        pcMode = Mode.working;
        break;
      case 0x05:
        pcMode = Mode.locked;
        break;
      case 0x09:
        pcMode = Mode.powerOff;
        break;
    }
    lockState = ByteUtil.toUint4(pcMode == Mode.locked ? 1 : 0);
  }

  @override
  String toString() {
    return 'R1RealTimeState{${super.toString()}';
  }
}

class R1RealTimeError extends AbsRealTimeError {
  static const errorCodes = [
    25,
    26,
    27,
    31,
    32,
    33,
    34,
    35,
    36,
    37,
    38,
    39,
    40,
    41,
    42,
    43,
    44,
    45,
    46,
    47,
    48,
    49,
    50,
    51,
    52,
    53,
    54,
    55,
    56,
    57,
    58,
    59,
    60,
    61,
    62,
    63,
    64,
    65,
    66,
    67,
    68,
    69,
    70,
    71,
    72,
    73,
    77,
    78,
    79,
    80,
    81,
    82,
    83,
    84,
    87,
    88,
    89,
    90,
    91,
    92,
    93,
    95,
    96,
    97,
    98,
    99,
    100,
    101
  ];

  R1RealTimeError.fromErrorCodeMsgRsp(Uint8ClampedList bytes) : super.fromBytes(bytes, 0) {
    originalValue = ByteUtil.bytes2Uint32Le(bytes);
  }

  bool hasVisibleWarningError() {
    return errorCodes.contains(originalValue.value);
  }
}

class R1AllRealTimeData extends AbsAllRealTimeInfo {
  R1AllRealTimeData(R1RealTimeInfo realTimeInfo, R1RealTimeState realTimeState, R1RealTimeError realTimeError) : super(realTimeInfo, realTimeState, realTimeError);
}
